package main

import (
	"context"
	"strconv"
	"strings"

	"google.golang.org/protobuf/proto"
	"smeb.xyz/pub/websocket-subandpub-cluster/internal/handlerwebsocket/protos"
)

type GrpcServiceServer struct {
}

// GetServerInfo implements protos.GrpcServiceServer.
func (*GrpcServiceServer) GetServerInfo(context.Context, *protos.GetServerInfoRequest) (*protos.GetServerInfoResponse, error) {
	panic("unimplemented")
}

// PublishToSomebodyInChannel implements protos.GrpcServiceServer.
func (*GrpcServiceServer) PublishToSomebodyInChannel(ctx context.Context, req *protos.PublishToSomebodyInChannelRequest) (*protos.PublishToSomebodyInChannelResponse, error) {

	suc, err := Redis.SMembers(ctx, req.Channel).Result()
	if err != nil {
		return nil, err
	}

	req.Id, req.Timestamp = GenerateMessageId(ZapLogger)
	data, err := proto.Marshal(req)
	if err != nil {
		ZapLogger.Fatal("marshaling error: ", err)
	}
	AddOneSomebodyTaskToQueue(SomebodyJob{
		Channel:          &req.Channel,
		Data:             &data,
		Members:          &req.Receivers,
		ChannelSubServer: &suc,
	})

	return &protos.PublishToSomebodyInChannelResponse{
		Code:      200,
		Msg:       "发布消息成功",
		Id:        req.Id,
		Timestamp: req.Timestamp,
	}, nil
}

// SendKickedOutMsg implements protos.GrpcServiceServer.
func (*GrpcServiceServer) SendKickedOutMsg(ctx context.Context, req *protos.KickedOutRequest) (*protos.KickedOutResponse, error) {
	panic("unimplemented")
}

// CreateNewChannel implements protos.WsClusterServiceServer.
func (*GrpcServiceServer) CreateNewChannel(ctx context.Context, req *protos.CreateNewChannelRequest) (*protos.CreateNewChannelResponse, error) {
	channel := GetRandomString(36)
	ii, ee := Redis.SAdd(ctx, channel, []string{"const"}).Result()
	if ee != nil || ii == 0 {
		return nil, ee
	}
	Redis.SAdd(ctx, Channel_Redis_key, channel).Result()
	return &protos.CreateNewChannelResponse{
		Channel: channel,
	}, nil
}

// DeleteChannel implements protos.WsClusterServiceServer.
func (*GrpcServiceServer) DeleteChannel(ctx context.Context, req *protos.DeleteChannelRequest) (*protos.DeleteChannelResponse, error) {
	i, e := Redis.Del(ctx, req.Channel).Result()
	if e != nil || i == 0 {
		return nil, e
	} else {
		servers, b := Redis.SMembers(ctx, req.Channel).Result()
		if b == nil {
			for _, server := range servers {
				RpcOnChannelDeleted(server, &protos.DeleteChannelRequest{
					Channel: req.Channel,
				})
			}
			Redis.SRem(ctx, Channel_Redis_key, req.Channel).Result()

			return &protos.DeleteChannelResponse{
				Code: 200,
				Msg:  "删除频道成功",
			}, nil

		} else {
			return nil, b
		}
	}
}

// DeleteChannelMembers implements protos.WsClusterServiceServer.
func (*GrpcServiceServer) DeleteChannelMembers(ctx context.Context, req *protos.DeleteChannelMembersRequest) (*protos.DeleteChannelMembersResponse, error) {

	servers, b := Redis.SMembers(ctx, req.Channel).Result()
	if b == nil {
		for _, server := range servers {
			RpcDeleteChannelMembers(server, &protos.DeleteChannelMembersRequest{
				Channel: req.Channel,
				Members: req.Members,
			})
		}
	}

	return &protos.DeleteChannelMembersResponse{
		Code: 200,
		Msg:  "删除频道成员成功",
	}, nil
}

// GetChannelConnCount implements protos.WsClusterServiceServer.
func (*GrpcServiceServer) GetChannelConnCount(ctx context.Context, req *protos.GetChannelConnCountRequest) (*protos.GetChannelConnCountResponse, error) {
	data, e := Redis.SCard(ctx, req.Channel).Result()
	if e != nil {
		return nil, e
	} else {
		return &protos.GetChannelConnCountResponse{
			Count: data,
		}, nil
	}
}

// MultipleIdentitySubscribleChannel implements protos.WsClusterServiceServer.
func (*GrpcServiceServer) MultipleIdentitySubscribleChannel(ctx context.Context, req *protos.MultipleIdentitySubscribleChannelRequest) (*protos.MultipleIdentitySubscribleChannelResponse, error) {

	for _, member := range req.Members {
		memberU := strconv.FormatUint(member, 10)
		memberInfo, e := Redis.Get(ctx, memberU).Result()
		if e == nil {
			i := strings.Split(memberInfo, "-")
			RpcMultiUserSubscribleChannel(i[0], &protos.MultipleIdentitySubscribleChannelRequest{
				Channel: req.Channel,
				Members: req.Members,
			})
		}
	}

	return &protos.MultipleIdentitySubscribleChannelResponse{
		Code: 200,
		Msg:  "多用户订阅频道成功",
	}, nil
}

// PublishToChannel implements protos.WsClusterServiceServer.
func (*GrpcServiceServer) PublishToChannel(ctx context.Context, req *protos.PublishToChannelRequest) (*protos.PublishToChannelResponse, error) {

	suc, err := Redis.SMembers(ctx, req.Channel).Result()
	if err != nil {
		return nil, err
	}

	req.Id, req.Timestamp = GenerateMessageId(ZapLogger)
	data, err := proto.Marshal(req)
	if err != nil {
		ZapLogger.Fatal("marshaling error: ", err)
	}
	// 在线发送
	AddOneTaskToQueue(Job{
		Channel:          &req.Channel,
		Data:             &data,
		ChannelSubServer: &suc,
	})

	return &protos.PublishToChannelResponse{
		Code:      200,
		Msg:       "发布消息成功",
		Id:        req.Id,
		Timestamp: req.Timestamp,
	}, nil
}

// PublishToSomeoneInChannel implements protos.WsClusterServiceServer.
func (*GrpcServiceServer) PublishToSomeoneInChannel(ctx context.Context, req *protos.PublishToSomeoneInChannelRequest) (*protos.PublishToSomeoneInChannelResponse, error) {

	suc, err := Redis.SMembers(ctx, req.Channel).Result()
	if err != nil {
		return nil, err
	}

	req.Id, req.Timestamp = GenerateMessageId(ZapLogger)
	data, err := proto.Marshal(req)
	if err != nil {
		ZapLogger.Fatal("marshaling error: ", err)
	}

	AddOneSomeoneTaskToQueue(SomeoneJob{
		Channel:          &req.Channel,
		Data:             &data,
		Member:           &req.Receiver,
		ChannelSubServer: &suc,
	})

	return &protos.PublishToSomeoneInChannelResponse{
		Code:      200,
		Msg:       "发布消息成功",
		Id:        req.Id,
		Timestamp: req.Timestamp,
	}, nil
}
